home *** CD-ROM | disk | FTP | other *** search
- /*
- * imagetext.c
- *
- * Copyright (C) 1989, 1991, Craig E. Kolb
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- * $Id: imagetext.c,v 4.0 91/07/17 14:42:42 kolb Exp Locker: kolb $
- *
- * $Log: imagetext.c,v $
- * Revision 4.0 91/07/17 14:42:42 kolb
- * Initial version.
- *
- */
- #include "texture.h"
- #include "image.h"
- #include "imagetext.h"
-
- #define INTERP(v) (text->lo + (v)*(text->hi - text->lo))
-
- /*
- * Create Image texture.
- * Image texture has so many options that there's usually no
- * nice way to parse without resorting to additional keywords.
- * Thus the ImageTextCreate routine only reads the image to be used;
- * all but ->component must be set by hand. The routine
- * ImageTextSetComponent is provided to set the component and
- * ensure that the image being used is appropriate.
- */
- ImageText *
- ImageTextCreate(imagefile)
- char *imagefile;
- {
- ImageText *text;
-
- text = (ImageText *)Calloc(1, sizeof(ImageText));
- text->component = COLOR; /* texture all colors by default*/
- /*
- * Only apply one copy of the texture by default
- */
- text->tileu = text->tilev = 0;
- text->lo = 0.; text->hi = 1.;
- text->smooth = FALSE;
- text->mapping = UVMappingCreate();
- text->image = ImageRead(imagefile);
- return text;
- }
-
- /*
- * Set image texture to apply to given component,
- * ensuring that the image that is being used is compatible.
- */
- void
- ImageTextSetComponent(text, component)
- ImageText *text;
- int component;
- {
- switch (component) {
- case COLOR: /* usual case, texture on amb, diff, spec, body */
- case AMBIENT:
- case DIFFUSE:
- case SPECULAR:
- case BODY:
- /* all of the above can use 1 or 3 channel images */
- if (text->image->chan != 1 && text->image->chan != 3) {
- RLerror(RL_ABORT,
- "Image %s must have 1 or 3 channels\n",
- text->image->filename);
- }
- break;
- case REFLECT:
- case TRANSP:
- case SPECPOW:
- case BUMP:
- case INDEX:
- /* the above need 1 channel images */
- if (text->image->chan != 1) {
- RLerror(RL_ABORT, "Image %s must have 1 channel\n",
- text->image->filename);
- }
- break;
- }
- text->component = component;
- }
-
- void
- ImageTextApply(text, prim, ray, pos, norm, gnorm, surf)
- ImageText *text;
- Geom *prim;
- Ray *ray;
- Vector *pos, *norm, *gnorm;
- Surface *surf;
- {
- Float fx, fy;
- Float outval[4], outval_u[4], outval_v[4];
- Float u, v;
- Surface tmpsurf;
- int ix, iy;
- int rchan, gchan, bchan;
- Vector dpdu, dpdv, ntmp;
-
- /*
- * First, find the floating point location in image coords.
- * Then set ix, iy to the integer location in image coords and
- * use fx, fy to represent the subpixel position.
- */
- if (text->component == BUMP)
- TextToUV(text->mapping, prim, pos, gnorm, &u, &v,
- &dpdu, &dpdv);
- else
- TextToUV(text->mapping, prim, pos, gnorm, &u, &v,
- (Vector *)NULL, (Vector *)NULL);
- /*
- * Handle tiling at this point.
- */
- if (TileValue(text->tileu, text->tilev, u, v))
- return;
- u -= floor(u);
- v -= floor(v);
- fx = u * (Float) text->image->width;
- fy = v * (Float) text->image->height;
- ix = fx;
- iy = fy;
- fx = fx - (Float) ix;
- fy = fy - (Float) iy;
-
- if (text->image->has_alpha) {
- /* Alpha channel is 0 */
- rchan = 1;
- gchan = 2;
- bchan = 3;
- } else {
- rchan = 0;
- gchan = 1;
- bchan = 2;
- }
-
- if (text->image->chan == 1) {
- gchan = rchan;
- bchan = rchan;
- }
-
- ImageIndex(text->image, ix, iy, fx, fy, text->smooth, outval);
-
- /*
- * escape when alpha is zero, 'cause there is no change
- */
- if (text->image->has_alpha && (outval[0] < 0.001))
- return;
-
- if (text->component != COLOR || text->surf == (Surface *)NULL) {
- tmpsurf = *surf;
- } else {
- tmpsurf = *text->surf;
- }
-
- switch (text->component) {
- case COLOR: /* amb, diff, spec */
- tmpsurf.spec.r *= outval[rchan];
- tmpsurf.spec.g *= outval[gchan];
- tmpsurf.spec.b *= outval[bchan];
- tmpsurf.diff.r *= outval[rchan];
- tmpsurf.diff.g *= outval[gchan];
- tmpsurf.diff.b *= outval[bchan];
- tmpsurf.amb.r *= outval[rchan];
- tmpsurf.amb.g *= outval[gchan];
- tmpsurf.amb.b *= outval[bchan];
- break;
- case AMBIENT: /* ambient */
- tmpsurf.amb.r *= INTERP(outval[rchan]);
- tmpsurf.amb.g *= INTERP(outval[gchan]);
- tmpsurf.amb.b *= INTERP(outval[bchan]);
- break;
- case DIFFUSE: /* diffuse */
- tmpsurf.diff.r *= INTERP(outval[rchan]);
- tmpsurf.diff.g *= INTERP(outval[gchan]);
- tmpsurf.diff.b *= INTERP(outval[bchan]);
- break;
- case SPECULAR: /* specular */
- tmpsurf.spec.r *= INTERP(outval[rchan]);
- tmpsurf.spec.g *= INTERP(outval[gchan]);
- tmpsurf.spec.b *= INTERP(outval[bchan]);
- break;
- case BODY: /* transmitted */
- tmpsurf.body.r *= INTERP(outval[rchan]);
- tmpsurf.body.g *= INTERP(outval[gchan]);
- tmpsurf.body.b *= INTERP(outval[bchan]);
- break;
- case REFLECT: /* specular reflectivity */
- tmpsurf.reflect *= INTERP(outval[rchan]);
- break;
- case TRANSP: /* specular transmittance */
- tmpsurf.transp *= INTERP(outval[rchan]);
- break;
- case SPECPOW: /* specpow */
- tmpsurf.srexp *= INTERP(outval[rchan]);
- break;
- case INDEX: /* index of refraction */
- tmpsurf.index *= INTERP(outval[rchan]);
- break;
- case BUMP: /* bump map */
- ImageIndex(text->image,
- (ix == text->image->width - 1) ? 0 : ix+1,
- iy, fx, fy,
- text->smooth, outval_u);
- ImageIndex(text->image, ix,
- (iy == text->image->height - 1) ? 0 : iy+1,
- fx, fy,
- text->smooth, outval_v);
- MakeBump(norm, &dpdu, &dpdv,
- INTERP(outval_u[rchan] - outval[rchan]),
- INTERP(outval_v[rchan] - outval[rchan]));
- return;
- }
-
- if (text->image->has_alpha && (outval[0] < 0.999)) {
- /*
- * image partial coverage means blend surf and text->surf
- */
- SurfaceBlend(surf, &tmpsurf, 1. - outval[0], outval[0]);
- } else {
- /*
- * image full coverage means use text->surf
- */
- *surf = tmpsurf;
- }
- }
-